programming4us
           
 
 
SQL Server

SQL Server 2008 : Developing Custom Managed Database Objects (part 2) - Developing Managed Stored Procedures

- Free product key for windows 10
- Free Product Key for Microsoft office 365
- Malwarebytes Premium 3.7.1 Serial Keys (LifeTime) 2019
3/23/2011 9:18:22 AM

Developing Managed Stored Procedures

Stored procedures are a great starting point for getting into SQLCLR because they are easy to implement. To do so, right-click your new project in VS’s Solution Explorer and then select Add, Stored Procedure. Name your new class StoredProcedures.cs. A partial class of that name opens in the VS code window. Note that VS automatically adds the required reference to Microsoft.SqlServer.Server and its associated using statement. Microsoft.SqlServer.Server contains the SqlProcedure attribute required for turning ordinary methods into SQLCLR stored procedures.

Change your autogenerated method name from StoredProcedures to GetProductReviews. Next, if you’re not working in VS, you need to decorate this method with the SqlProcedure attribute.

Attributes and the Implementation Contract

If you’ve never used attributes, you can think of them as metadata that tells callers, usually through reflection, that the decorated element (known as the target) meets some criterion. All the managed objects you create in this article require certain attributes to be applied; otherwise, they cannot be used in a SQL Server context.

The classes you build must also implement particular methods and/or method signatures to be built and deployed successfully to SQL Server. This is known as fulfilling the implementation contract. For stored procedures, fulfilling this contract requires that your method be marked static. Its return type must be one of the following: void, Int32, Nullable<Int32>, or SqlInt32. Its input parameters and their types are up to you, but keep in mind that these must be convertible from a T-SQL context to a .NET context. These are the only contract requirements to be filled for stored procedures.

Note

It makes sense that these methods must be marked static because they are called by the CLR host via the class’s type object, rather than via an object instance (that is, AssemblyName.ClassName.StaticMethodName(Parameters)).


Object-oriented (OO) purists might suggest that this way of creating managed SQL Server objects could have been done in a more OO-friendly way if the contract to be filled required overriding the methods of an abstract class or implementing interfaces. The static requirement, however, currently makes this impossible because static members are not inherited and cannot be used to implement interface members.

The constructor for the SqlProcedure attribute is overloaded to either take zero parameters or take one parameter that is actually a list of named parameters. (Having a list of named parameters in the attribute signature is common to most of the attributes used in this article, although the choice of named parameter pairs varies from attribute to attribute.)

For the SqlStoredProcedureAttribute, only one named parameter exists: Name. You use Name when you want to name the method one thing but have the name it generates for use in a T-SQL context to be another name.

The code in Listing 1 illustrates the use of a named parameter in this attribute and contains a simple example of how to generate a set of rows using SQLCLR.

Listing 1. A Managed Stored Procedure That Generates a Set of Rows
[SqlProcedure(Name = "clr_GetProductManuals")]
public static void GetProductManuals()
{
using (SqlConnection ContextConnection =
new SqlConnection("context connection=true"))
{
SqlDataRecord record =
new SqlDataRecord(
new SqlMetaData[]
{
new SqlMetaData("ProductModelId",
SqlDbType.Int),
new SqlMetaData("Manual",
SqlDbType.Xml)
}
);

SqlContext.Pipe.SendResultsStart(record);

using (SqlCommand Command = new SqlCommand())
{
Command.CommandText =
@"SELECT TOP 10 ProductModelId, Instructions
FROM Production.ProductModel
WHERE Instructions IS NOT NULL";

Command.Connection = ContextConnection;
ContextConnection.Open();

using (SqlDataReader reader = Command.ExecuteReader())
{
while (reader.Read())
{
int ProductModelId = reader.GetInt32(0);
SqlXml ManualXml = reader.GetSqlXml(1);

record.SetInt32(0, ProductModelId);
record.SetSqlXml(1, ManualXml);
SqlContext.Pipe.SendResultsRow(record);
}
}

SqlContext.Pipe.SendResultsEnd();
}
}
}


Although this example does not require it, if your SQLCLR code needs to access server resources (such as files), it would be necessary to change your assembly’s permission set from the default of SAFE to EXTERNAL_ACCESS. To do to this in VS, right-click your project in Solution Explorer and select Properties. Then, on the left side of the window, select the Database tab. (Note that the Database tab is the place where VS stores a connection string matching your database reference. You can change that here as well.) Under the Permission Level drop-down, change the value from Safe to External and save the project. You can also type in the name of the SQL Server login (under Assembly Owner), which will be specified for the AUTHORIZATION parameter of CREATE ASSEMBLY during deployment by VS.

The idea behind the code in Listing 1 is that, given a set of rows from Production.ProductModel, the procedure generates a result set of only those products that have a reference manual. Let’s examine the new objects in this code.

The Context Connection

In our managed procedure, we use a special ADO.NET connection string ("context connection=true”), known as the context connection string, to connect to the session of SQL Server under which our managed stored procedure is currently executing (that is, once the assembly has been deployed and is running in a T-SQL context).

Objects in Microsoft.SqlServer.Server

Our managed procedure also uses some specialized objects to send data to SQL Server through the active connection:

  • SqlContext— This represents the server execution context for the managed routine. You can think of it as the line of communication between the .NET and SQL Server environments.

  • SqlContext.Pipe— SqlContext holds the crucial Pipe property, used to send SqlDataRecord objects or text messages to the method’s caller, which, by the way, may be either another managed routine (via ADO.NET) or any T-SQL user code.

  • SqlDataRecord— This is an abstraction that represents a record in any given table. The schema of columns for a SqlDataRecord object is created by using SqlMetaData objects, as shown in Listing 46.1.

  • SqlMetaData— An array of SqlMetaData objects is passed to the constructor of each SqlDataRecord. Each SqlMetaData object defines the name, type, precision, scale, and so forth for its target column via its overloaded constructors.

Returning to the code in Listing 46.1, before looping through our SqlDataReader object (reader), we call Pipe.SendResultsStart, passing a SqlDataRecord object whose structure matches our desired output. This tells SQL Server that our procedure is about to send rows (to the caller) having a specific structure.

Looping through the reader (using while (reader.Read())), we select the values to be returned. To do this, we use the Set[DataTypeName] methods on our SqlDataRecord object called record. When our values are all set, we call SqlContext.Pipe.SendResultsRow(record) to return these data.

After the code has finished sending data to the client, it cleans up by calling Pipe.SendResultsEnd. Note that the Pipe object also has an ExecuteAndSend method that takes a SqlCommand parameter, executes it, and sends all the results back to the caller in one fell swoop. In addition, you can query the status of the Pipe object by checking its IsSendingResults Boolean property. You can even send an informational text message (similar to T-SQL’s print function) to the caller, using Pipe.Send("Text"). Send() is overloaded to accept a SqlDataRecord object or a SqlDataReader object that contains the data to be returned.

Building and Deploying the Assembly

At this point, you can build the VS project and then choose the new Deploy command from VS’s Build menu. In this step, VS generates the T-SQL DDL scripts needed to upload our assembly to SQL Server and then add our managed stored procedure to the AdventureWorks2008 database.

You’ve already seen the CREATE ASSEMBLY DDL that VS uses. For now, let’s assume that you’ve already uploaded the assembly once. In this scenario, you need to execute the following T-SQL to replace that assembly with a newly compiled version of the same:

ALTER ASSEMBLY AssemblyName
[AUTHORIZATION LoginName]
FROM StringPathToAssemblyDll | BinaryDataValue
[PERMISSION_SET = (SAFE | EXTERNAL_ACCESS | UNSAFE) ]

You can also use ALTER ASSEMBLY to upload your C# class files so that when you’re debugging any exceptions you get source code line numbers in the stack dump (seamlessly reported by SQL Server’s built-in error reporting mechanism). Here’s an example:

ALTER ASSEMBLY AssemblyName ADD FILE FROM FilePath

Tip

The use of any managed user-defined types in your database prevents an assembly from being dropped or altered until any type already in use is dropped (because it is a dependency).


After you load your assembly to SQL Server, you can execute the following DDL to add your managed stored procedure to AdventureWorks2008:

CREATE PROCEDURE [dbo].[clr_GetProductManuals]
WITH EXECUTE AS CALLER
AS
EXTERNAL NAME
[ProjectName].[StoredProcedures].[GetProductManuals]

The new WITH EXECUTE AS CALLER clause tells SQL Server that the permissions for executing the procedure should be those of its caller. (See the “EXECUTE AS” Books Online topic for more information.)

The new EXTERNAL NAME keywords tell SQL Server that the routines or types being created belong to a specific class in a loaded assembly. The dot-notation for the string parameter of EXTERNAL NAME is as follows:

AssemblyName.ClassName.RoutineOrTypeName

You’ll see this parameter again in the DDL of the other managed objects we’ll soon create.

To view the objects created during script execution or VS deployment, open the Object Explorer in SQL Server Management Studio (SSMS), expand the AdventureWorks2008 database node, and then expand the Programmability node. There you can find the Assemblies node. (The managed objects in the assembly are kept in their respective folders.) If you right-click an assembly and view its properties, another window appears where you can view or change the assembly’s permissions.

Debugging Managed Code

Now open a new query window in SSMS and test your new managed stored procedure, just as you would any other. Try the following:

EXEC clr_GetProductManuals
Go
ProductModelId Manual
-----------------------------------------------------------------------------
7 <root xmlns="http://schemas.microsoft.com/sqlserver/2004/07/...
10 <root xmlns="http://schemas.microsoft.com/sqlserver/2004/07/...
...
(10 rows(s) affected.)


Let’s try debugging with VS. By default, every SQL Server project is created with a Test Scripts folder and a file called Test.sql. Test.sql (or any other .sql file in a SQL Server project) is kind of like a hybrid of a code file and a query window. In this file you can execute a batch of arbitrary database commands, and you can also set breakpoints on each code line. The output of the commands appears in the Database Output section of VS’s Output window.

Enter the same T-SQL in Test.sql that you just did in SSMS. Then set a breakpoint on any line. Press F5 or click the Run button, and you can now execute and step through your managed stored procedure in a single environment.

You may first need to acknowledge a dialog window that asks whether it’s okay to enable SQLCLR debugging on the server. Answer in the affirmative, unless you’re in a nontesting environment. (One caveat: As with remote debugging in general, this setup may not work in all environments.)

Other -----------------
- SQL Server 2008 : Profiler Usage Scenarios (part 2)
- SQL Server 2008 : Profiler Usage Scenarios (part 1) - Analyzing Slow Stored Procedures or Queries & Deadlocks
- SQL Server 2008 : Defining Server-Side Traces
- SQL Server 2008 : SQL Server Profiler - Replaying Trace Data
- SQL Server 2008 : SQL Server Profiler - Saving and Exporting Traces
- SQL Server 2008 : SQL Server Profiler - Creating Traces
- SQL Server 2008 : SQL Server Profiler Architecture
- SQL Server 2008: Administering Database Objects - Working with Tables (part 7) - Partitions
- SQL Server 2008: Administering Database Objects - Working with Tables (part 6) - Compression
- SQL Server 2008: Administering Database Objects - Working with Tables (part 5) - Sparse Columns
- SQL Server 2008: Administering Database Objects - Working with Tables (part 4) - Check Constraints
- SQL Server 2008: Administering Database Objects - Working with Tables (part 3) - Foreign Key Constraints
- SQL Server 2008: Administering Database Objects - Working with Tables (part 2) - Primary Key Constraints & Unique Constraints
- SQL Server 2008: Administering Database Objects - Working with Tables (part 1) - Default Constraints
- SQL Server 2008: Administering Database Objects - Working with Database Snapshots
- Programming with SQL Azure : WCF Data Services (part 3)
- Programming with SQL Azure : WCF Data Services (part 2) - Creating the Client Application
- Using XML in SQL Server 2008: Relational Data As XML - The FOR XML Modes (part 4) - EXPLICIT Mode
- Using XML in SQL Server 2008: Relational Data As XML - The FOR XML Modes (part 3) - AUTO Mode
- Programming with SQL Azure : WCF Data Services (part 1)
 
 
 
Top 10
 
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
- Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
- Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
- First look: Apple Watch

- 3 Tips for Maintaining Your Cell Phone Battery (part 1)

- 3 Tips for Maintaining Your Cell Phone Battery (part 2)
programming4us programming4us